package com.ptu.spzx.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ptu.spzx.common.exception.ptuException;
import com.ptu.spzx.domain.Exam.Exam;
import com.ptu.spzx.domain.Exam.ExamExampaper;
import com.ptu.spzx.domain.Exam.Exampaper;
import com.ptu.spzx.domain.Exam.dto.StuAnswerExampaperQuestionDTO;
import com.ptu.spzx.domain.Exam.vo.SimpleExampaperQuestionVo;
import com.ptu.spzx.domain.Exam.vo.SimpleExampaperVVo;
import com.ptu.spzx.domain.Stu.StuAnswer;
import com.ptu.spzx.domain.Stu.Vo.SimpleStuAnswerVo;
import com.ptu.spzx.domain.Stu.Vo.StuAnswerVo;
import com.ptu.spzx.domain.Stu.Vo.StuScoreVo;
import com.ptu.spzx.domain.Stu.dto.StuAnswerDto;
import com.ptu.spzx.domain.Stu.dto.StuAnswerScoreDto;
import com.ptu.spzx.mapper.ExamExampaperMapper;
import com.ptu.spzx.mapper.ExamMapper;
import com.ptu.spzx.mapper.ExampaperMapper;
import com.ptu.spzx.mapper.StuAnswerMapper;
import com.ptu.spzx.model.vo.common.ResultCodeEnum;
import com.ptu.spzx.service.IStuAnswerService;
import com.ptu.spzx.utils.BeanCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author YT
 * @since 2024-01-28
 */
@Service
public class StuAnswerServiceImpl extends ServiceImpl<StuAnswerMapper, StuAnswer> implements IStuAnswerService {
    @Autowired
    private StuAnswerMapper stuAnswerMapper;
    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private ExampaperMapper exampaperMapper;
    @Autowired
    private ExamExampaperMapper examExampaperMapper;

    @Override
    public void submitStuAnswer(StuAnswerDto stuAnswerDto) {
        Exam exam = examMapper.selectOne(new LambdaQueryWrapper<Exam>().eq(Exam::getExamId, stuAnswerDto.getExamId()));
        if(exam==null){
           throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        ExamExampaper examExampaper = examExampaperMapper.selectOne(new LambdaQueryWrapper<ExamExampaper>()
                .eq(ExamExampaper::getExamId, stuAnswerDto.getExamId())
                .eq(ExamExampaper::getEpId, stuAnswerDto.getEpId()));
        if(examExampaper==null){
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        StuAnswer stuAnswerExist=stuAnswerMapper.selectByStuId(stuAnswerDto.getStuId());
        if(stuAnswerExist!=null){
            throw new ptuException(ResultCodeEnum.DATA_EXIST);
        }
        String examEndTime = exam.getExamEndTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try{
            Date end = sdf.parse(examEndTime);
            Date now = sdf.parse(sdf.format(new Date()));
            if(now.after(end)){
                throw new ptuException(ResultCodeEnum.TIME_BEGIN);
            }
        }catch (Exception e){
            throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
        }
        List<StuAnswerExampaperQuestionDTO> stuAnswer = stuAnswerDto.getStuAnswer();
        Exampaper exampaper = exampaperMapper.selectById(stuAnswerDto.getEpId());
        if(exampaper==null){
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        //获取标准答案
        String jsonString = JSON.toJSONString(exampaper.getQuestions());
        List<StuAnswerExampaperQuestionDTO> epAnswer = JSON.parseArray(jsonString, StuAnswerExampaperQuestionDTO.class);
        List<Float> scoreList = new ArrayList<>();
        if(epAnswer.size()==stuAnswer.size()){
           for(int i=0;i<epAnswer.size();i++){
               StuAnswerExampaperQuestionDTO ExampaperQuestionDTO = epAnswer.get(i);
               StuAnswerExampaperQuestionDTO stuAnswerExampaperQuestionDTO = stuAnswer.get(i);
               Integer questionType = ExampaperQuestionDTO.getQuestionType();
               String questionAnswer = ExampaperQuestionDTO.getQuestionAnswer();
               Integer isSingleSelect = ExampaperQuestionDTO.getIsSingleSelect();
               Integer outOfOrder = ExampaperQuestionDTO.getOutOfOrder();
               String stuQuestionAnswer = stuAnswerExampaperQuestionDTO.getQuestionAnswer();
               //题目小题分数
               Float num = ExampaperQuestionDTO.getScore();
               Float score = autoJudge(questionType,questionAnswer,stuQuestionAnswer,num,isSingleSelect,outOfOrder);
               scoreList.add(score);
               //预留接口
           }
        }
        Float systemScore = scoreList.stream().filter(score -> score != -99f).reduce(0f, Float::sum);
        StuAnswer stuAnswerReal = StuAnswer.builder()
                .stuId(stuAnswerDto.getStuId())
                .epId(stuAnswerDto.getEpId())
                .examId(stuAnswerDto.getExamId())
                .stuAnswer(JSON.toJSONString(stuAnswerDto.getStuAnswer()))
                .systemScore(systemScore)
                .epStatus(1)
                .stuScore(systemScore)
                .stuScorelist(JSON.toJSONString(scoreList))
                .startTime(stuAnswerDto.getStartTime())
                .leaveTimes(stuAnswerDto.getLeaveTimes())
                .submitTime(stuAnswerDto.getSubmitTime())
                .build();
        //判断未交卷的学生
        if(stuAnswerDto.getEpStatus()!=null&&stuAnswerDto.getEpStatus()==0){
            stuAnswerReal.setEpStatus(0);
        }
        stuAnswerMapper.insert(stuAnswerReal);
    }

    @Override
    public void submitStuScore(StuAnswerScoreDto stuAnswerScoreDto) {
        String stuScoreList = stuAnswerScoreDto.getStuScorelist();
        String stuId = stuAnswerScoreDto.getStuId();
        Long epId = stuAnswerScoreDto.getEpId();
        Long examId = stuAnswerScoreDto.getExamId();
        Float stuScore = 0f;
        //字符串解析
        JSONArray numString = JSON.parseArray(stuScoreList);
        ArrayList<Float> arr = new ArrayList<>();
        for(Object num:numString){
            if (Float.parseFloat(num.toString()) < 0) {
                throw new ptuException(ResultCodeEnum.DATA_ERROR);
            }
            arr.add(Float.parseFloat(num.toString()));
            stuScore += Float.parseFloat(num.toString());
        }
        BigDecimal stuScores = new BigDecimal(stuScore);
        stuScores = stuScores.setScale(0, BigDecimal.ROUND_HALF_UP);
        List<Integer> indexList = new ArrayList();
        //学生答案的解析
        Exampaper exampaper = exampaperMapper.selectById(epId);
//        List<SimpleExampaperQuestionVo> epAnswers = exampaper.getEpAnswer();
        List<SimpleExampaperVVo> epAnswer1 = exampaper.getQuestions();
        for(SimpleExampaperVVo simpleExampaperVVo:epAnswer1){
            List<SimpleExampaperQuestionVo> epAnswers = simpleExampaperVVo.getQues();
            int index=0;
            int a=0;
            for (Object epAnswer : epAnswers) {
                //字符串转换JSONObject获取里面的对象
                String json = JSON.toJSONString(epAnswer);
                JSONObject jsonObject = JSONObject.parseObject(json);
                int questionType = jsonObject.getIntValue("questionType");
                if (questionType==3) {
                    index = a;
                    indexList.add(index);
                }
                if (questionType==4) {
                    index = a;
                    indexList.add(index);
                }
                a+=1;
            }
        }
        Float[] doubleArr = new Float[arr.size()];
        for (int j = 0; j < arr.size(); j++) {
            doubleArr[j] = Float.parseFloat(arr.get(j).toString());
        }
        float newStuScore = stuScore;
        for (int i : indexList) {
            double number = doubleArr[i];
            newStuScore -= number;
        }
        BigDecimal newStuScores = new BigDecimal(newStuScore);
        newStuScores = newStuScores.setScale(0, BigDecimal.ROUND_HALF_UP);
        Map<String, Object> params = new HashMap<>();
        try {
            params.put("stuScorelist", stuScoreList);
            params.put("stuScore", stuScores);
            params.put("systemScore", newStuScores);
            params.put("stuId", stuId);
            params.put("epId", epId);
            params.put("examId", examId);
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.DATA_ERROR);
        }
        stuAnswerMapper.UpdateStuScore(params);
    }

    @Override
    public PageInfo<StuAnswer> getStuScoreList(Long examId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<StuAnswer> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StuAnswer::getExamId,examId)
                .eq(StuAnswer::getEpStatus,3);
        PageHelper.startPage(pageNum,pageSize);
        List<StuAnswer> stuAnswers = stuAnswerMapper.selectList(lambdaQueryWrapper);
        if(stuAnswers==null){
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        PageInfo<StuAnswer> pageInfo = new PageInfo<>(stuAnswers);
        return pageInfo;
    }

    @Override
    public StuAnswer getStuAnswer(String stuId,Long epId) {
       if(stuId==null||stuId==" "){
           throw new ptuException(ResultCodeEnum.PARAM_NULL);
       }
        StuAnswer stuAnswer = stuAnswerMapper.selectByStuIdByEpId(stuId,epId);
        String answer = stuAnswer.getStuAnswer();
        JsonNode stuAnwser;
        ObjectMapper objectMapper = new ObjectMapper()
                .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        try {
            stuAnwser = objectMapper.readValue(answer, JsonNode.class);
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.DATA_ERROR);
        }
       if(stuAnswer!=null){
           return stuAnswer;
       }else {
        throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
       }
    }

    private Float autoJudge(Integer questionType, String questionAnswer, String stuQuestionAnswer, Float num,Integer isSingleSelect,Integer outOfOrder) {
        if(questionType.equals(0)){
            //选择题的判题逻辑
            return choiceJudge(questionAnswer,stuQuestionAnswer,num,isSingleSelect);
        }else if(questionType.equals(1)){
            //填空题的判题逻辑
            return fillJudge(questionAnswer,stuQuestionAnswer,num,outOfOrder);
        }else if(questionType.equals(2)){
            //判断题的判题逻辑
            return judgeJudge(questionAnswer,stuQuestionAnswer,num);
        } else if (questionType.equals(3)) {
            //简答题的判断逻辑 新功能开发
            return 0f;
        } else if (questionType.equals(4)) {
            //材料题的判断逻辑 新功能开发
            return 0f;
        }
        return 0f;
    }

    //判断题的判题逻辑
    private Float judgeJudge(String questionAnswer, String stuQuestionAnswer, Float num) {
        if(!"false".equals(stuQuestionAnswer)&&!"true".equals(stuQuestionAnswer)){
            return 0f;
        }
        if(questionAnswer.equals(stuQuestionAnswer)){
            return Float.parseFloat(String.format("%.2f",num));
        }
        return 0f;
    }

    //填空题的判题逻辑
    private Float fillJudge(String questionAnswer, String stuQuestionAnswer, Float num,Integer outOfOrder) {
        JSONArray epArray = JSON.parseArray(questionAnswer);
        JSONArray stuArray = JSON.parseArray(stuQuestionAnswer);
        Float score = 0f;
        //是否乱序 1代表乱序 0代表不乱序
        if (1 == outOfOrder) {
            for (Object stu : stuArray) {
                if (stu.toString().length() > 0) {
                    for (Object epA : epArray) {
                        if (epA.toString().contains(stu.toString())) {
                            score += num / epArray.size();
                        }
                    }
                }
            }
        } else {
            for (int i = 0; i < epArray.size(); i++) {
                Object epObj = epArray.get(i);
                Object stuObj = stuArray.get(i);
                if(stuObj==null){
                    return 0f;
                }
                if (epObj.toString().equals(stuObj.toString())) {
                    score += num / epArray.size();
                }
            }
        }
        return Float.parseFloat(String.format("%.2f", score));
    }

    //选择题的判题逻辑
    private Float choiceJudge(String questionAnswer, String stuQuestionAnswer, Float num,Integer isSingleSelect) {
        if(isSingleSelect==1&&stuQuestionAnswer.equals(questionAnswer)){
            return num;
        }else if(isSingleSelect==0){
            JSONArray epArray = JSON.parseArray(questionAnswer);
            JSONArray stuArray = JSON.parseArray(stuQuestionAnswer);
            for (Object stuAns : stuArray) {
                if (epArray.indexOf(stuAns) == -1) {
                    return 0f;
                }
                epArray.remove(stuAns);
            }
            if (epArray.size() == 0) {
                return Float.parseFloat(String.format("%.2f", num));
            } else {
                return Float.parseFloat(String.format("%.2f", num/2));
            }
        }
        return 0f;
    }
}
